﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.ServiceModel;
using Mall.Infrastructure.Log;


namespace Mall.Infrastructure.Container
{
    /// <summary>
    /// 应用程序扩展
    /// </summary>
    public static class AppDomainExtensions
    {
        /// <summary>
        /// 获取接口容器
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static InterfaceContainer GetContainer(this AppDomain app)
        {
            return InterfaceContainer.GetInstance();
        }

    }

    /// <summary>
    /// 接口容器(单例模式)
    /// </summary>
    public class InterfaceContainer
    {
        /// <summary>
        /// 配置字典
        /// </summary> 
        private List<ServiceElement> ServiceList;

        private List<ServiceHost> HostList;

        /// <summary>
        /// 接口菜单
        /// </summary>
        private static Dictionary<string, Object> InterFaceList;

        /// <summary>
        /// 唯一存在的对象
        /// </summary>
        private static InterfaceContainer Instance;


        /// <summary>
        /// 上锁对象
        /// </summary>
        private static readonly object _object = new object();

        /// <summary>
        /// 唯一获取对象的入口
        /// </summary>
        /// <returns></returns>
        public static InterfaceContainer GetInstance()
        {
            if (Instance == null)
            {
                lock (_object)
                {
                    if (Instance == null)
                    {
                        Instance = new InterfaceContainer();
                    }
                }
            }

            return Instance;
        }

        /// <summary>
        /// 私有构造函数
        /// </summary>
        private InterfaceContainer()
        {
            //初始化集合
            ServiceList = new List<ServiceElement>();
            //初始化容器接口集合
            InterFaceList = new Dictionary<string, object>();

            //接口注入
            InterfaceInject();
        }

        /// <summary>
        /// 接口注入
        /// </summary>
        private void InterfaceInject()
        {
            //获取容器配置
            var config = ConfigurationManager.GetSection("Container") as ContainerSection;
            if (config == null)
            {
                throw new Exception("配置里面未配置Container节点");
            }

            foreach (ServiceElement item in config.Services)
            {
                ServiceList.Add(item);
            }

        }

        /// <summary>
        /// 获取接口
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public T GetSerivce<T>() where T:class
        {
            T result = null;
            //查找是否有相关配置
            Type info = typeof(T);
            var item = ServiceList.Find(m => m.Contract == info.FullName);
            if(item==null)
            {
                throw new Exception(String.Format("Container.config里面未找到Contract为{0}的配置", info.FullName));
            }
            //缓存存在就直接返回
            if (InterFaceList.ContainsKey(info.FullName))
            {
                result = InterFaceList[info.FullName] as T;
            }
            else
            {
                //接口实现
                switch (item.Type)
                {
                    case "Wcf":
                        {
                            ChannelFactory<T> factory = new ChannelFactory<T>(item.Name);
                            result = factory.CreateChannel();

                        } break;
                    case "Local":
                        {
                            result = AppDomain.CurrentDomain.Load(item.Namespace).CreateInstance(item.Name) as T;
                        } break;
                    default:
                        {
                            throw new Exception(String.Format("Container.config里面Contract为{0}的配置里面Type非法", info.FullName));
                        };
                }
                if (result == null)
                {
                    throw new Exception(String.Format("{0}接口通过{1}实例化失败", info.FullName,item.Name));
                }
                InterFaceList.Add(info.FullName, result);
            }
            return result;
        }

        public void HostStart()
        {
            var log = AppDomain.CurrentDomain.GetLogManage(); 
            //获取容器配置
            var config = ConfigurationManager.GetSection("Container") as ContainerSection;
            HostList = new List<ServiceHost>();
            foreach (HostElement item in config.Hosts)
            {
                Type type= AppDomain.CurrentDomain.Load(item.Namespace).GetTypes().Where(m=>m.FullName==item.Contract).FirstOrDefault();
                if(type==null)
                {
                    throw new Exception(String.Format("{0}类别通过{1}初始化失败", item.Contract,item.Namespace));
                }
                ServiceHost service = new ServiceHost(type);
                HostList.Add(service);
            }
            foreach (var host in HostList)
            {
                host.Open();
                log.Info(string.Format("{0}服务已经启动......", host.Description.Name));
            }

        }

        public void HostClose()
        {
            var log = AppDomain.CurrentDomain.GetLogManage(); 
            foreach (var host in HostList)
            {
                host.Close();
                log.Info(string.Format("{0}服务已经关闭......", host.Description.Name));
            }
        }

    }
}
